home *** CD-ROM | disk | FTP | other *** search
/ QuickTime 1.0 for Developers / QuickTime 1.0 for Developers.iso / Programming Stuff / Sample Code / MovieController Exerciser / BigEasy2.c next >
Text File  |  1991-08-13  |  35KB  |  1,747 lines

  1. /*
  2.     File:        BigEasy2.c
  3.  
  4.     Copyright:    © 1990 by Apple Computer, Inc., all rights reserved.
  5.  
  6.     This file is used in these builds: Warhol
  7.  
  8.     Change History (most recent first):
  9.  
  10.         <26>     8/12/91    MD        support for timing profiler nastiness
  11.         <25>      7/3/91    PH        qd. is bad under old think
  12.         <24>     6/28/91    dvb        Make it work with/without MacHeaders in LSC5.
  13.         <23>      6/4/91    PH        compilin'
  14.         <22>      6/3/91    dvb        Just hackin.
  15.         <21>     5/28/91    JB        Added prototypes for BigEasy Proc Ptrs
  16.         <20>     5/27/91    PH        to compile again...
  17.         <19>     5/25/91    JB        OLD_THINK_C && TOOLBOX_LINKED
  18.         <18>     5/23/91    PH        changes for THINK 5
  19.         <17>     5/22/91    PH        new style prototypes
  20.         <16>      5/6/91    PH        nifty line after about...
  21.         <15>      5/5/91    dvb        Latest features, and App-Events for document open.
  22.        
  23.         <14>     4/25/91    JB        Changing to new THINK C interface files
  24.         <13>     4/19/91    PH        i like content clicks
  25.         <12>     4/19/91    dvb        Add WindowEventProc
  26.         <11>     3/29/91    PH        minor activate fix
  27.         <10>     3/29/91    dvb        Repair deactivate vs closewindow conflict, roll in latest cool
  28.                                     features.
  29.          <9>      3/9/91    dvb        Adjust to work with or without (LSC) mac headers
  30.          <8>      3/7/91    JB        Adjusting for using MacHeaders
  31.          <7>      3/1/91    dvb        Trivial new functions
  32.          <6>     2/24/91    dvb        Various cool new calls
  33.          <5>     2/18/91    dvb        Miscellaneous Updates
  34.          <4>      1/9/91    JB        Increasing ItemsPerMenu & #Menus
  35.          <3>    11/21/90    JB        Changes for INIT & mpw compatability
  36.          <2>    11/17/90    dvb        Pass on unused command-keys to document windows
  37.         <1>    11/17/90    dvb        New again after 1st CD pressing! Yay!
  38.  
  39.     To Do:
  40. */
  41.  
  42. /* file: BigEasy2.c
  43.   *
  44.   * Started 30 June 1988, more or less.
  45.   *
  46.   * A set of routines to allow the quick development
  47.   * of simple Macintosh applications.
  48.   *
  49.   */
  50.  
  51.  
  52. #define BigEasy2
  53.  
  54. #include <QuickDraw.h>
  55. #include <GestaltEqu.h>
  56. #include <Events.h>
  57. #include <AppleEvents.h>
  58. #include <Resources.h>
  59. #include <Menus.h>
  60. #include <ToolUtils.h>
  61. #include <Menus.h>
  62. #include <Windows.h>
  63. #include <Dialogs.h>
  64. #include <Memory.h>
  65. #include <Desk.h>
  66. #include <Fonts.h>
  67. #include <OSEvents.h>
  68. #include <SegLoad.h>
  69.  
  70. /* #define THINK_C_PROFILE /* */
  71. #if defined(TIMING_PROFILE) || defined(STACK_KILLER)
  72.     #include "stack killer.h"
  73. #endif
  74.  
  75. #include "BigEasy2.h"
  76.  
  77. /************************************
  78. * Limits
  79. ************************************/
  80. #define kMMax 10            /* Number of menus in menubar */
  81. #define kMIMax 50            /* Number of items per menu */
  82. #define kMenuNameMax 32        /* Length of a menu title */
  83.  
  84. #define kStagStepX 7
  85. #define kStagStepY 7
  86. #define kStagLimX 97
  87. #define kStagLimY 37
  88.  
  89. /************************************
  90. * Constants
  91. ************************************/
  92. #define    kOSEvent                        app4Evt    /* event used by MultiFinder */
  93. #define    kSuspendResumeMessage            1        /* high byte of suspend/resume event message */
  94. #define    kResumeMask                    1        /* bit of message field for resume vs. suspend */
  95.  
  96. #define kWinPosType 'bewP'
  97. #define trapExitToShell 0xA9F4
  98.  
  99.  
  100.  
  101. /************************************
  102. * Major BigEasy2 Structures
  103. ************************************/
  104.  
  105. typedef struct tEasyWindow
  106.     {
  107.     boolean wUsed;
  108.     long flags;
  109.     boolean wGrowable;
  110.     beUpdateProcPtr wUpdateProc;
  111.     beClickProcPtr wClickProc;
  112.     beKeyProcPtr wKeyProc;
  113.     beGoAwayProcPtr wGoAwayProc;
  114.     beZoomProcPtr wZoomProc;
  115.     beActivateProcPtr wActivateProc;
  116.     beDeactivateProcPtr wDeactivateProc;
  117.     beIdleProcPtr wIdleProc;
  118.     beResizeProcPtr wResizeProc;
  119.     beGrowWindowProcPtr wGrowWindowProc;
  120.     beEventProcPtr wEventProc;
  121.     WindowPtr wWindow;
  122.     } tEasyWindow;
  123.  
  124. typedef struct
  125.     {
  126.     short ref;
  127.     char mark;
  128.     char enable;
  129.     char cmdEquiv;
  130.     beMenuProcPtr proc;
  131.     } tEasyMenuItem;
  132.  
  133. /************************************
  134. * Globals
  135. ************************************/
  136.  
  137. Rect gResizeLim = {50,50,1000,1000};
  138. tEasyWindow **gEasyWindowListH;            /* Handle to array of window objects    */
  139. tEasyWindow *gEasyWindowList;            /* Pointer to array of window objects    */
  140. short gEasyWindowListSize;                /* Number of window objects allocated    */
  141.  
  142. /*** Menus ***/
  143. MenuHandle gMenuHandleList[kMMax];        /* MenuHandles indexed by MenuID's         */
  144. short gMenuLength[kMMax];
  145. char gMenuName[kMMax][kMenuNameMax];
  146. tEasyMenuItem gMenu[kMMax][kMIMax];
  147. short gMenuCount;                        /* How many menus defined */
  148. short gCurrentMenu;                        /* the one to add to */
  149. MenuHandle gMenuEdit;                    /* Which one is the edit menu? */
  150.  
  151. /*** Phantom Menu ***/
  152. MenuHandle phantomMenuH = 0;
  153.  
  154. /*** About ***/
  155. beAboutProcPtr gAboutProc;
  156. char gAboutS0[256];
  157.  
  158. /*** Application Edit Commands ***/
  159. beWNumCallProcPtr gAppUndoProc,gAppCutProc,gAppCopyProc,gAppPasteProc,gAppClearProc;
  160.  
  161. /*** Global Status ***/
  162. beAboutProcPtr gMasterIdleProc;
  163. short gStagX,gStagY;
  164. WindowPtr gLastFrontIdle;
  165. short gLastFrontWindowNumber;
  166. short gSleep;
  167. short gCoolDragState;
  168. Point gCoolDragPoint;
  169. WindowPtr gCoolDragWindow;
  170. Boolean gInvalidMenuBar;
  171.  
  172. void *gOldExitToShell;
  173.  
  174. Boolean gHasAppleEvents;
  175.  
  176. /************************************
  177. * Prototypes
  178. ************************************/
  179. static void InitToolbox(void);
  180. static void CheckMenubar(void);
  181. static void EventLoop(void);
  182. static void InitBigEasy(void);
  183. static void InstallMyExitToShell(void);
  184. static pascal void MyExitToShell(void);
  185. static void GetGrowRect(WindowPtr,Rect*);
  186. static void EnoughEasyWindows(short);
  187. static void FrontDAEdits(void);
  188. static tEasyWindow *GoodWNum(short);
  189. static Boolean CoolBigEasyCmdKeys(short key);
  190.  
  191. static void DoMyAbout(void);
  192. static void BEUndo(short);
  193. static void BECopy(short);
  194. static void BECut(short);
  195. static void BEPaste(short);
  196. static void BEClear(short);
  197. static void BENull(void);
  198. static void MenuClick(Point p);
  199. static void DeleteIndexedMenuItem(short menu,short item);
  200. static Boolean DoKeyPress(long k);
  201. static void MenuPoint(long theclick);
  202. static void StartMenus(void);
  203. static short ScanWindowList(WindowPtr w);
  204. static void DoMouseClick(EventRecord *event);
  205. void MyDrawGrowIcon(WindowPtr w);
  206.  
  207. void main(void);
  208.  
  209. /************************************
  210. * Some useful routines
  211. ************************************/
  212.  
  213. void InitToolbox(void)
  214.     {
  215. #ifdef THINK_C
  216.     #if THINK_C < 5
  217.         InitGraf(&thePort);
  218.     #else
  219.         InitGraf(&qd.thePort);
  220.     #endif
  221. #else
  222.     InitGraf(&qd.thePort);
  223. #endif
  224.     InitFonts();
  225.     FlushEvents(0xffff,0);
  226.     InitWindows();
  227.     InitMenus();
  228.     InitDialogs(0);
  229.     TEInit();
  230.     InitCursor();
  231.     }
  232.  
  233.  
  234. void GetGrowRect(WindowPtr w,Rect *r)
  235.     {
  236.     register Rect *gr;
  237.  
  238.     gr = r;
  239.     *gr = w->portRect;
  240.     gr->left = gr->right - 15;
  241.     gr->top = gr->bottom - 15;
  242.     }
  243.  
  244. void GoWatch(void)
  245.     {
  246.     SetCursor(*(Cursor**)GetCursor(4));
  247.     }
  248.  
  249. void GoArrow(void)
  250.     {
  251. #ifdef THINK_C
  252.     #if THINK_C < 5
  253.         SetCursor(&arrow);
  254.     #else
  255.         SetCursor(&qd.arrow);
  256.     #endif
  257. #else
  258.     SetCursor(&qd.arrow);
  259. #endif
  260.     }
  261.  
  262. void GoCursor(short c)
  263. /*
  264.   * Attempt to set to cursor ID c,
  265.   * but skip it if not there.
  266.   */
  267.     {
  268.     register Cursor **cur;
  269.  
  270.     cur = (Cursor **)GetCursor(c);
  271.     if(cur)
  272.         SetCursor(*cur);
  273.     }
  274.  
  275. static void EnoughEasyWindows(short n)
  276. /*
  277.   * If there are less than n window objects in the list,
  278.   * grow the handle appropriately.
  279.   */
  280.     {
  281.     short i;
  282.  
  283.     n++;
  284.     if(gEasyWindowListSize < n)
  285.         {
  286.         HUnlock((Handle)gEasyWindowListH);
  287.         SetHandleSize((Handle)gEasyWindowListH,sizeof(tEasyWindow) * (long)n);
  288.         HLock((Handle)gEasyWindowListH);
  289.         gEasyWindowList = *gEasyWindowListH;
  290.  
  291.         for(i = gEasyWindowListSize; i < n; i++)
  292.             gEasyWindowList[i].wUsed = 0;
  293.  
  294.         gEasyWindowListSize = n;
  295.         }
  296.     }
  297.  
  298. static tEasyWindow *GoodWNum(short n)
  299. /*
  300.   * return true if n is the number of an
  301.   * existing, used window.
  302.   */
  303.     {
  304.     register tEasyWindow *thisWindow;
  305.     if(n<0 || n>=gEasyWindowListSize)
  306.         return 0;
  307.     thisWindow = &gEasyWindowList[n];
  308.     if(thisWindow->wUsed)
  309.         return thisWindow;
  310.     else
  311.         return 0;
  312.     }
  313.  
  314.  
  315. static void FrontDAEdits(void)
  316. /*
  317.  * Check the front window. If it's a DA,
  318.  * enable all edit menu options.
  319.  */
  320.     {
  321.     WindowRecord *w;
  322.  
  323.     w = (WindowRecord*)FrontWindow();
  324.     if(w->windowKind < 0)                                    /* Any click in a DA window: */
  325.         EnDisEdits(1,1,1,1,1);                                /* enable edit menu. */
  326.     }
  327.  
  328.  
  329. void DoMyAbout(void)
  330.     {
  331.     DialogPtr d;
  332.     Handle h;
  333.     short hit;
  334.  
  335.     if(gAboutProc)
  336.         (*gAboutProc)();
  337.     else
  338.         {
  339.         h = GetResource('DLOG',1962);                            /* does it exist? */
  340.         if( (ResError()==0) && (h!=nil) )
  341.             {
  342.             ParamText((StringPtr)gAboutS0,0,0,0);
  343.             d = GetNewDialog(1962,0,(WindowPtr)-1);
  344.             ModalDialog(nil,&hit);
  345.             DisposDialog(d);
  346.             }
  347.         }
  348.     }
  349.  
  350. void SetMasterIdle(r)
  351.     beAboutProcPtr r;
  352.     {
  353.     gMasterIdleProc = r;
  354.     }
  355.  
  356. void SetWindowResizeProc(short n,beResizeProcPtr resizeProc)
  357. /*
  358.   * Sets the procedure which gets called when the window is resized
  359.   */
  360.     {
  361.     tEasyWindow *thisWindow;
  362.  
  363.     thisWindow = GoodWNum(n);
  364.     if(thisWindow)
  365.         thisWindow->wResizeProc = resizeProc;
  366.     }
  367.  
  368. void SetWindowGrowWindowProc(short n,beGrowWindowProcPtr growWindowProc)
  369. /*
  370.   * Sets the procedure which gets called when the window grows.
  371.   *   Allows alternate to GrowWindow.
  372.   */
  373.     {
  374.     tEasyWindow *thisWindow;
  375.  
  376.     thisWindow = GoodWNum(n);
  377.     if(thisWindow)
  378.         thisWindow->wGrowWindowProc = growWindowProc;
  379.     }
  380.  
  381. void SetWindowZoomProc(short n,beZoomProcPtr zoomProc)
  382.     {
  383.     register tEasyWindow *thisWindow;
  384.  
  385.     thisWindow = GoodWNum(n);
  386.     if(thisWindow)
  387.         thisWindow->wZoomProc = zoomProc;
  388.     }
  389.  
  390. void SetWindowEventProc(short n,beEventProcPtr eventProc)
  391.     {
  392.     register tEasyWindow *thisWindow;
  393.  
  394.     thisWindow = GoodWNum(n);
  395.     if(thisWindow)
  396.         thisWindow->wEventProc = eventProc;
  397.     }
  398.  
  399. long GetWindowFlags(short n)
  400.     {
  401.     tEasyWindow *thisWindow;
  402.  
  403.     if(!(thisWindow = GoodWNum(n)))
  404.         return 0;
  405.  
  406.     return thisWindow->flags;
  407.     }
  408.  
  409. void SetWindowFlags(short n,long flags)
  410.     {
  411.     tEasyWindow *thisWindow;
  412.  
  413.     if(!(thisWindow = GoodWNum(n)))
  414.         return;
  415.  
  416.     thisWindow->flags = flags;
  417.     }
  418.  
  419. void SetAbout(StringPtr progName,StringPtr s0,beAboutProcPtr aboutProc)
  420. /*
  421.  * Sets the program's name in the about box, and
  422.  * sets the second string as ParamText 0 (^0)
  423.  * for the about dialog, 1962.
  424.  */
  425.     {
  426.     short i;
  427.     
  428.     SetItem(gMenuHandleList[1],1,(StringPtr)progName);
  429.  
  430.     for(i=0; i<256; i++)
  431.         gAboutS0[i] = *s0++;
  432.  
  433.     gAboutProc = aboutProc;
  434.     } 
  435.  
  436. /************************************
  437. * Error Handling
  438. ************************************/
  439.  
  440. void InstallMyExitToShell(void)
  441. /*
  442.   * Add my HatStrap call to
  443.   * the classic routine, "ExitToShell"
  444.   */
  445.     {
  446.     gOldExitToShell =  (void *) NGetTrapAddress(trapExitToShell, ToolTrap);
  447.     NSetTrapAddress((long) MyExitToShell, trapExitToShell, ToolTrap);
  448.     }
  449.  
  450. pascal void MyExitToShell(void)
  451. /*
  452.   * My exit routine, which does
  453.   * all the good cleanup.
  454.   */
  455.     {
  456.     Hatstrap();
  457.     NSetTrapAddress((long) gOldExitToShell, trapExitToShell, ToolTrap);
  458.     ExitToShell();
  459.     }    
  460.  
  461. void FailNil(long x)
  462. /*
  463.   * If x is zero, post an error
  464.   * alert and quit the program.
  465.   */
  466.     {
  467.     if(!x)
  468.         {
  469.         Alert(200,nil);
  470.         Debugger();
  471.         ExitToShell();
  472.         }
  473.     }
  474.  
  475. void FailOSErr(long x)
  476. /*
  477.   * If x isn't zero, post an error
  478.   * alert and quit the program.
  479.   */
  480.     {
  481.     if(x)
  482.         {
  483.         Debugger();
  484.         Alert(200,nil);
  485.         ExitToShell();
  486.         }
  487.     }
  488.  
  489. /************************************
  490. * Some inherent methods
  491. ************************************/
  492.  
  493. void BEUndo(short n)
  494.     {
  495.     if(!SystemEdit(0))
  496.         (*gAppUndoProc)(n);
  497.     }
  498.  
  499. void BECut(short n)
  500.     {
  501.     if(!SystemEdit(2))
  502.         (*gAppCutProc)(n);
  503.     }
  504.  
  505. void BECopy(short n)
  506.     {
  507.     if(!SystemEdit(3))
  508.         (*gAppCopyProc)(n);
  509.     }
  510.  
  511. void BEPaste(short n)
  512.     {
  513.     if(!SystemEdit(4))
  514.         (*gAppPasteProc)(n);
  515.     }
  516.  
  517. void BEClear(short n)
  518.     {
  519.     if(!SystemEdit(5))
  520.         (*gAppClearProc)(n);
  521.     }
  522.  
  523. void BENull(void){}
  524.  
  525.  
  526. /************************************
  527. * Menu Action Routines
  528. ************************************/
  529.  
  530. Boolean DoKeyPress(long k)
  531.     {
  532.     register long thePoint;
  533.     register Boolean didIt;
  534.  
  535.     thePoint = MenuKey((char)k);
  536.     didIt = (thePoint>>16) != 0;
  537.     if(didIt)
  538.         MenuPoint(thePoint);
  539.  
  540.     return didIt;
  541.     }
  542.     
  543. void MenuClick(Point p)
  544.     {
  545.     KeyMap     theKeys;
  546.     Boolean    putBack = false;
  547.     short    oldID;
  548.     
  549.     if (phantomMenuH) {
  550. #if THINK_C < 5
  551.         GetKeys( &theKeys );
  552. #else
  553.         GetKeys(theKeys);
  554. #endif
  555.         
  556.         if ((theKeys[1]&4) == 0) {
  557.             putBack = true;
  558.             oldID = (**phantomMenuH).menuID;
  559.             DeleteMenu( oldID );
  560.             }
  561.         }
  562.     MenuPoint(MenuSelect(p));
  563.     if (putBack)
  564.         {
  565.         InsertMenu(phantomMenuH,oldID);
  566.         }
  567.     }
  568.  
  569. void MenuPoint(long theclick)
  570.     {
  571.     register short mID,mItem;
  572.     char DAname[30];
  573.     short wNum;
  574.     tEasyWindow *thisWindow;
  575.     register beMenuProcPtr aProc;
  576.     register tEasyMenuItem *emi;
  577.  
  578.     mID = theclick>>16;
  579.     mItem = theclick & 0xffff;
  580.  
  581.     if(mID == 0) return;
  582.  
  583.     if(mID == 1)                            /* Apple menu */
  584.         {
  585.         if(mItem == 1)                        /* Its either the about box */
  586.             DoMyAbout();
  587.         else    
  588.             {                                    /* Or a DA */
  589.             GetItem(gMenuHandleList[1],mItem,(StringPtr)DAname);
  590.             OpenDeskAcc((StringPtr)DAname);
  591.             }
  592.         }
  593.     else
  594.         {
  595.         wNum = gLastFrontWindowNumber;
  596.         thisWindow = GoodWNum(wNum);
  597.         if(thisWindow)                                    /* if one of our window in front, setport    */
  598.             SetPort(thisWindow->wWindow);
  599.  
  600.         emi = &gMenu[mID][0];
  601.         aProc = emi->proc;
  602.         if(aProc)                                        /* call the menu's routine, if any        */
  603.             (*aProc)(wNum,mItem,gMenu[mID][mItem].ref);
  604.  
  605.         emi = &gMenu[mID][mItem];
  606.         aProc = emi->proc;
  607.         if(aProc)                                        /* call the item's routine, if any        */
  608.             (*aProc)(wNum,mItem,emi->ref);
  609.         }
  610.  
  611.     HiliteMenu(0);
  612.     }
  613.  
  614. char dAbout[] = "\pAbout ";
  615.  
  616. void StartMenus(void)
  617. /*
  618.  * Start with just an About box, and some DA's.
  619.  */
  620.     {
  621.     char aboutS[255];
  622.     MenuHandle applemenu;
  623.  
  624.     BlockMove(&dAbout[0],aboutS,dAbout[0]+1);            /* "About" */
  625.     BlockMove((StringPtr )0x910 + 1,aboutS + aboutS[0] + 1, *(StringPtr )0x910); /* ProgName */
  626.     aboutS[0] += *((StringPtr )0x910);
  627.     aboutS[aboutS[0] + 1] = '...';
  628.     aboutS[0]++;
  629.  
  630.     applemenu = NewMenu(1,(StringPtr)"\p");                /* Apple menu: ID 1                    */
  631.     AppendMenu(applemenu,(StringPtr)aboutS);
  632.     AppendMenu(applemenu,(StringPtr)"\p(-");
  633.     AddResMenu(applemenu,'DRVR');
  634.     InsertMenu(applemenu,0);
  635.     DrawMenuBar();
  636.     gMenuHandleList[1] = applemenu;
  637.  
  638.     gMenuCount = 1;                        /* Next menu added will be ID 2        */
  639.     gCurrentMenu = 1;
  640.     gMenuLength[1] = 0;                    /* No items, really, in Apple menu        */
  641.     }
  642.  
  643. MenuHandle InstallMenu(StringPtr s,beMenuProcPtr action,short ref)
  644. /*
  645.  * Start a new menu with name s
  646.  */
  647.     {
  648.     register tEasyMenuItem *emi;
  649.     register MenuHandle mh;
  650.  
  651.     gMenuCount++;                                /* new menu                        */
  652.     gCurrentMenu = gMenuCount;
  653.  
  654.     if(*s > kMenuNameMax-1)
  655.         *s = kMenuNameMax-1;
  656.  
  657.     gMenuLength[gCurrentMenu] = 0;
  658.     mh = NewMenu(gCurrentMenu,(StringPtr)s);
  659.     gMenuHandleList[gCurrentMenu] = mh;
  660.     InsertMenu(mh,0);
  661.  
  662.     if(ref < 0)
  663.         {
  664.         DisableItem(mh,0);
  665.         ref =- ref;
  666.         }
  667.  
  668.     emi = &gMenu[gCurrentMenu][0];
  669.  
  670.     emi->proc = action;
  671.     emi->ref = ref;
  672.     gInvalidMenuBar = true;                    /* redraw soon */
  673.     BlockMove(s,gMenuName[gCurrentMenu],*s+1);
  674.     return mh;
  675.     }
  676.  
  677. void InstallMenuItem(StringPtr s,beMenuProcPtr action,short ref)
  678. /*
  679.  * Add an item to the last menu, and associate a routine with it.
  680.  */
  681.     {
  682.     register MenuHandle mh;
  683.     register tEasyMenuItem *emi;
  684.     register short item;
  685.  
  686.  
  687.     mh = gMenuHandleList[gCurrentMenu];
  688.     gMenuLength[gCurrentMenu]++;
  689.     item = gMenuLength[gCurrentMenu];
  690.     emi = &gMenu[gCurrentMenu][item];
  691.  
  692.     if (ref < 0)
  693.         {
  694.         DisableItem(mh,item);
  695.         ref =- ref;
  696.         emi->enable = 0;
  697.         }
  698.     else
  699.         emi->enable = 1;
  700.  
  701.     AppendMenu(mh,(StringPtr)s);
  702.     emi->proc = action;
  703.     emi->ref = ref;
  704.     emi->mark = 0;
  705.     if(*(s+*s-1) == '/')
  706.         emi->cmdEquiv = *(s+*s);
  707.     else
  708.         emi->cmdEquiv = 0;
  709.     }
  710.  
  711. void DeleteMenuItem(short ref)
  712. /*
  713.  * Remove all menu items with
  714.  * refcon ref.
  715.  */
  716.     {
  717.     short menu;
  718.     short item;
  719.  
  720.     for(menu = 1; menu <= gMenuCount; menu++)
  721.         for(item = gMenuLength[menu]; item > 0; item--)
  722.             {
  723.             if(gMenu[menu][item].ref == ref)
  724.                 DeleteIndexedMenuItem(menu,item);
  725.             }
  726.     }
  727.  
  728. void DeleteIndexedMenuItem(short menu,short item)
  729.     {
  730.     StringPtr oldStrings;
  731.     MenuHandle mh;
  732.     short i;
  733.     short itemCount;
  734.     register tEasyMenuItem *emi;
  735.     register StringPtr w;
  736.  
  737.     itemCount = gMenuLength[menu];
  738.     mh = gMenuHandleList[menu];
  739.     oldStrings = (StringPtr)NewPtr(256 * (itemCount));
  740.     FailNil((long)oldStrings);
  741.  
  742.     for(i = 1; i<=itemCount; i++)
  743.         GetItem(mh,i,(StringPtr)&oldStrings[(i-1)*256]);
  744.  
  745.     DeleteMenu(menu);
  746.     DisposeMenu(mh);
  747.  
  748.     mh = NewMenu(menu,(StringPtr)gMenuName[menu]);
  749.     emi = &gMenu[menu][1];
  750.     w = oldStrings;
  751.     for(i = 1; i<=itemCount; i++)
  752.         {
  753.         if(i != item)
  754.             {
  755.             if(emi->cmdEquiv)
  756.                 {
  757.                 *(w+*w+1) = '/';
  758.                 *(w+*w+2) = emi->cmdEquiv;
  759.                 *w = *w + 2;
  760.                 }
  761.             AppendMenu(mh,(StringPtr)w);
  762.             }
  763.         emi++;
  764.         w += 256;
  765.         }
  766.  
  767.     emi = &gMenu[menu][item];
  768.     for(i = item; i<itemCount; i++)
  769.         {
  770.         *emi = *(emi+1);
  771.         emi++;
  772.         }
  773.  
  774.     gMenuLength[menu]--;
  775.     itemCount--;
  776.  
  777.     emi = &gMenu[menu][1];
  778.     for(i = 1; i<=itemCount; i++)
  779.         {
  780.         if(!emi->enable)
  781.             DisableItem(mh,i);
  782.         if(emi->mark)
  783.             SetItemMark(mh,i,emi->mark);
  784.         emi++;
  785.         }
  786.  
  787.     InsertMenu(mh,menu+1);
  788.     DisposPtr((Ptr)oldStrings);
  789.     }
  790.  
  791. void InstallEditMenu(Xundo,Xcut,Xcopy,Xpaste,Xclear)
  792. /*
  793.  * Start an edit menu, and put the first six things in.
  794.  */
  795.     beWNumCallProcPtr Xundo,Xcut,Xcopy,Xpaste,Xclear;
  796.     {
  797.     gAppUndoProc = Xundo;
  798.     gAppCutProc = Xcut;
  799.     gAppCopyProc = Xcopy;
  800.     gAppPasteProc = Xpaste;
  801.     gAppClearProc = Xclear;
  802.  
  803.     InstallMenu((StringPtr )"\pEdit",nil,0);
  804.     InstallMenuItem((StringPtr )"\px/Z",(beMenuProcPtr)BEUndo,-mUndo);            /* barfs because it is static */
  805.     InstallMenuItem((StringPtr )"\p(-",(beMenuProcPtr)BENull,0);
  806.     InstallMenuItem((StringPtr )"\px/X",(beMenuProcPtr)BECut,-mCut);
  807.     InstallMenuItem((StringPtr )"\px/C",(beMenuProcPtr)BECopy,-mCopy);
  808.     InstallMenuItem((StringPtr )"\px/V",(beMenuProcPtr)BEPaste,-mPaste);
  809.     InstallMenuItem((StringPtr )"\px/B",(beMenuProcPtr)BEClear,-mClear);
  810.  
  811.     gMenuEdit = gMenuHandleList[gCurrentMenu];
  812.  
  813.     EnDisEdits(-1,-1,-1,-1,-1);
  814.     }
  815.  
  816. void SetMenuItem(short ref,char enable,char isMarked,char mark,StringPtr s)
  817. /*
  818.   * Set all items with the reference number to the
  819.   * enable/disable state, with mark, and name s.
  820.   * pass enable + to enable, - to disable, and
  821.   * zero to leave alone.
  822.   */
  823.     {
  824.     short m,i;
  825.     MenuHandle mh;
  826.     register tEasyMenuItem *emi;
  827.  
  828.     for(m=1; m<=gMenuCount; m++)
  829.         {
  830.         mh = gMenuHandleList[m];
  831.         for(i=gMenuLength[m]; i>=0; i--)
  832.             {
  833.             emi = &gMenu[m][i];
  834.             if(emi->ref == ref)
  835.                 {
  836.                 if(enable)
  837.                     {
  838.                     if(!i)
  839.                         gInvalidMenuBar = true;
  840.                     if(enable > 0)
  841.                         {
  842.                         emi->enable = 1;
  843.                         EnableItem(mh,i);
  844.                         }
  845.                     else
  846.                         {
  847.                         emi->enable = 0;
  848.                         DisableItem(mh,i);
  849.                         }
  850.                     }
  851.                 if(i > 0)                    /* these only apply to items */
  852.                     {
  853.                     if(isMarked)
  854.                         if(isMarked > 0)
  855.                             {
  856.                             emi->mark = mark;
  857.                             SetItemMark(mh,i,mark);
  858.                             }
  859.                         else
  860.                             {
  861.                             emi->mark = 0;
  862.                             SetItemMark(mh,i,0);
  863.                             }
  864.                     if(s)
  865.                         SetItem(mh,i,(StringPtr)s);
  866.                     }
  867.                 }
  868.             }
  869.         }
  870.     }
  871.  
  872.  
  873.  
  874. void EnDisEdits(short Eundo,short Ecut,short Ecopy,short Epaste,short Eclear)
  875. /*
  876.  * For each edit menu entry,
  877.  * -1=disable, 1=enable, 0=leave alone.
  878.  */
  879.     {
  880.     SetMenuItem(mUndo,Eundo,false,0,(StringPtr )"\pUndo");
  881.     SetMenuItem(mCut,Ecut,false,0,(StringPtr )"\pCut");
  882.     SetMenuItem(mCopy,Ecopy,false,0,(StringPtr )"\pCopy");
  883.     SetMenuItem(mPaste,Epaste,false,0,(StringPtr )"\pPaste");
  884.     SetMenuItem(mClear,Eclear,false,0,(StringPtr )"\pClear");
  885.     }
  886.  
  887. void SetCurrentMenu(short ref)
  888. /*
  889.  * Set which menu will take
  890.  * future "InstallMenuItem"s.
  891.  */
  892.     {
  893.     register short i;
  894.  
  895.     for(i = 0; i<gMenuCount; i++)
  896.         {
  897.         if(gMenu[i][0].ref == ref)
  898.             gCurrentMenu = i;
  899.         }
  900.     }
  901.  
  902. short ScanWindowList(WindowPtr w)
  903. /*
  904.   * return a window number from a WindowPeek,
  905.   * or -1 if no known window.
  906.   */
  907.     {
  908.     short i;
  909.     tEasyWindow *wo;
  910.  
  911.     wo= &gEasyWindowList[0];
  912.  
  913.     for(i=0; i<gEasyWindowListSize; i++)
  914.         {
  915.         if (wo->wUsed && (wo->wWindow==w))
  916.             return i;
  917.         wo++;
  918.         }
  919.     return -1;
  920.     }
  921.  
  922.  
  923. /************************************
  924.     Mouse Action Routines
  925. ************************************/
  926. void DoMouseClick(EventRecord *event)
  927.     {
  928.     WindowPtr w;
  929.     short part;
  930.     register short wNum;
  931.     short i;
  932.     register tEasyWindow *thisEasyWindow;
  933.     Point p;
  934.     Rect r;
  935.     boolean tookEvent;
  936.  
  937.     p = event->where;
  938.     part = FindWindow (p, &w);
  939.     wNum = ScanWindowList(w);
  940.     thisEasyWindow = GoodWNum(wNum);
  941.  
  942.     switch (part)
  943.         {
  944.         case inDesk:
  945.             break;
  946.  
  947.         case inMenuBar:
  948.             MenuClick(p);
  949.             break;
  950.         
  951.         case inSysWindow:
  952.             SystemClick(event,w);
  953.             break;
  954.         
  955.         case inContent:
  956.         contentClick:
  957.             if (w != FrontWindow())                /* If clicked on a non-front window, */
  958.                 SelectWindow(w);                            /* bring it to the front. */
  959.             else if(thisEasyWindow)                            /* Click on front window: give click */
  960.                 {                                        /* to window's click routine. */
  961.                 SetPort(w);
  962.                 GlobalToLocal(&p);
  963.  
  964.                 ClipRect(&gBigRect);
  965.                 SetOrigin(0,0);
  966.  
  967.                 if(thisEasyWindow && thisEasyWindow->wEventProc)
  968.                     (*thisEasyWindow->wEventProc)(wNum,event,&tookEvent);
  969.                 else
  970.                     tookEvent = false;
  971.  
  972.                 if(!tookEvent)
  973.                     {
  974.                     register beClickProcPtr fp;
  975.  
  976.                     fp = thisEasyWindow->wClickProc;
  977.                     if(fp)
  978.                         (*fp)(wNum,p,
  979.                                 event->modifiers);
  980.                     }
  981.                 }
  982.             break;
  983.  
  984.         case inDrag:
  985.             if(((thisEasyWindow->flags & wCoolDrag)!=0) ^ ((event->modifiers & optionKey)!=0))
  986.                 {
  987.                 gCoolDragPoint = event->where;
  988.                 gCoolDragState = 1;
  989.                 gCoolDragWindow = w;
  990.                 if(!(event->modifiers & 256))
  991.                     SelectWindow(w);
  992.                 }
  993.             else
  994.                 if(Button())                                /* so quick title-bar clix */
  995.                     DragWindow(w,event->where,&gBigRect);    /* still work */
  996.                 else
  997.                     SelectWindow(w);
  998.             break;
  999.  
  1000.         case inGrow:
  1001.             if(thisEasyWindow && (thisEasyWindow->flags & wGrowable))
  1002.                 {
  1003.                 long oldSize,newSize;
  1004.                 beGrowWindowProcPtr fp;
  1005.                 beResizeProcPtr rsfp;
  1006.                 
  1007.                 SetPort(w);
  1008.                 GetGrowRect(w,&r);
  1009.                 InvalRect(&r);
  1010.  
  1011.                 fp = thisEasyWindow->wGrowWindowProc;
  1012.                 if(fp)
  1013.                     (*fp)(&newSize,wNum,w,event->where,&gResizeLim);
  1014.                 else
  1015.                     newSize = GrowWindow(w,event->where,&gResizeLim);
  1016.  
  1017.                 rsfp = thisEasyWindow->wResizeProc;
  1018.                 if(rsfp)
  1019.                     {
  1020.                     oldSize = ((long)(w->portRect.bottom-w->portRect.top)<<16) |
  1021.                             (w->portRect.right-w->portRect.left);
  1022.                     (*rsfp)(wNum,(Point *)&oldSize,(Point *)&newSize,event->modifiers);
  1023.                     }
  1024.                 else
  1025.                     SizeWindow(w,newSize&0xffff,newSize>>16,1);
  1026.  
  1027.                 GetGrowRect(w,&r);
  1028.                 InvalRect(&r);
  1029.                 }
  1030.             else
  1031.                 goto contentClick;
  1032.             break;
  1033.  
  1034.         case inGoAway:
  1035.             if(thisEasyWindow)
  1036.                 if (TrackGoAway(w,event->where))
  1037.                     {
  1038.                     beGoAwayProcPtr fp;
  1039.                     
  1040.                     fp = thisEasyWindow->wGoAwayProc;
  1041.                     if(fp)
  1042.                         (*fp)(wNum);
  1043.                     }
  1044.             break;
  1045.  
  1046.         /*
  1047.          * The following way to handle zoom only
  1048.          * applies to zooming to 1 state.  This does
  1049.          * not handle zooming in and out between 2
  1050.          * states.  Check IM IV.
  1051.          */
  1052.  
  1053.         case inZoomIn:    /* zoomBox */
  1054.         case inZoomOut:
  1055.             if(thisEasyWindow)
  1056.                 {
  1057.                 if (TrackBox(w,event->where,part))
  1058.                     {
  1059.                     beZoomProcPtr fp;
  1060.                     
  1061.                     fp = thisEasyWindow->wZoomProc;
  1062.                     if(fp)
  1063.                         (*fp)(wNum);
  1064.                     }
  1065.                 }
  1066.             break;
  1067.         }
  1068.     }
  1069.  
  1070. /************************************
  1071.     Window Action Routines
  1072. ************************************/
  1073.  
  1074. WindowPtr InstallWindow(short iNum,StringPtr iTitle,Rect *iRect,short iType,short iFlags,
  1075.         beUpdateProcPtr iUpdate,beClickProcPtr iClick,beKeyProcPtr iKey,beGoAwayProcPtr iGoAway,
  1076.         beActivateProcPtr iActivate,beDeactivateProcPtr iDeactivate,beIdleProcPtr iIdle)
  1077. /*
  1078.  * Add a window to BigEasy's list. If the window is
  1079.  * already up somewhere, bring it to the front and
  1080.  * visualize it.
  1081.  */
  1082.     {
  1083.     tEasyWindow *thisWindow;
  1084.     Rect stagRect,**oldPos;
  1085.     boolean isVisible;
  1086.     RgnHandle rh;
  1087.     KeyMap km;
  1088.     boolean opt;
  1089.  
  1090.     #if THINK_C < 5
  1091.         GetKeys(&km);
  1092.     #else
  1093.         GetKeys(km);
  1094.     #endif
  1095.  
  1096.     opt =km[58/8] &  (1<< (58%8) );
  1097.  
  1098.     isVisible = iNum>0;
  1099.     if(!isVisible)
  1100.         iNum = -iNum;
  1101.  
  1102.     EnoughEasyWindows(iNum);            /* Make sure there's space for new one        */
  1103.     thisWindow = &gEasyWindowList[iNum];
  1104.  
  1105.     if (thisWindow->wUsed)                /* something already assigned to this window? */
  1106.         {
  1107.         Show(iNum);
  1108.         goto goHome;
  1109.         }
  1110.  
  1111.     oldPos = (Rect **)Get1Resource(kWinPosType,iNum);    /* attempt to find saved window position        */
  1112.     rh = NewRgn();
  1113.     if(oldPos && !opt)                                /* (option key "forgets" old window spot        */
  1114.         RectRgn(rh,*oldPos);
  1115.     SectRgn(rh,*(RgnHandle *)0x9EE,rh);
  1116.     if(!EmptyRgn(rh))                                /* is save spot on the desktop?                */
  1117.         {
  1118.         stagRect = **oldPos;
  1119.         isVisible = stagRect.left < stagRect.right;            /* swap left and right for invisible            */
  1120.         if(!isVisible)
  1121.             SwapShort(stagRect.left,stagRect.right);
  1122.         }
  1123.     else
  1124.         {
  1125.         stagRect = *iRect;
  1126.         if(gStaggerWindows)
  1127.             {
  1128.             gStagX = (gStagX + kStagStepX)%kStagLimX;
  1129.             gStagY = (gStagY + kStagStepY)%kStagLimY;
  1130.             OffsetRect(&stagRect,gStagX,gStagY);
  1131.             }
  1132.         }
  1133.     DisposeRgn(rh);
  1134.  
  1135.     thisWindow->wUsed = 1;
  1136.  
  1137.     thisWindow->wWindow = NewCWindow(0,&stagRect,(StringPtr)iTitle,isVisible,
  1138.             ((iFlags & wZoomable) != 0) ? zoomDocProc : iType,
  1139.             (WindowPtr)-1,iGoAway!=0,0);
  1140.     SetPort(thisWindow->wWindow);
  1141.  
  1142.     thisWindow->flags = iFlags;
  1143.     thisWindow->wUpdateProc = iUpdate;
  1144.     thisWindow->wClickProc = iClick;
  1145.     thisWindow->wKeyProc = iKey;
  1146.     thisWindow->wGoAwayProc = iGoAway;
  1147.     thisWindow->wZoomProc = nil;
  1148.     thisWindow->wActivateProc = iActivate;
  1149.     thisWindow->wDeactivateProc = iDeactivate;
  1150.     thisWindow->wIdleProc = iIdle;
  1151.     thisWindow->wResizeProc = nil;
  1152.     thisWindow->wGrowWindowProc = nil;
  1153.     thisWindow->wEventProc = nil;
  1154. goHome:
  1155.     return thisWindow->wWindow;
  1156.     }
  1157.  
  1158. void UninstallWindow(short iNum)
  1159.     {
  1160.     register tEasyWindow *thisWindow;
  1161.     register beDeactivateProcPtr fp;
  1162.  
  1163.     gCoolDragState = 0;                    /* just in case we were dragging the dissappeared window */
  1164.  
  1165.     if(!(thisWindow = GoodWNum(iNum)))
  1166.         return;
  1167.  
  1168.     fp = thisWindow->wDeactivateProc;
  1169.     if(fp)
  1170.         (*fp)(iNum);
  1171.     CloseWindow(thisWindow->wWindow);
  1172.     thisWindow->wUsed = 0;
  1173.     }
  1174.  
  1175. void Show(short iNum)
  1176.     {
  1177.     register tEasyWindow *thisWindow;
  1178.  
  1179.     thisWindow = GoodWNum(iNum);
  1180.     if(thisWindow)
  1181.         {
  1182.         if(!((WindowPeek)(thisWindow->wWindow))->visible)    /* If so, just show it, and bring it to the front. */
  1183.             ShowWindow(thisWindow->wWindow);
  1184.         SelectWindow(thisWindow->wWindow);
  1185.         }
  1186.     }
  1187.  
  1188. void Hide(short iNum)
  1189. /*
  1190.   * Just do HideWindow to the
  1191.   * specified window number.
  1192.   */
  1193.     {
  1194.     register tEasyWindow *thisWindow;
  1195.  
  1196.     gCoolDragState = 0;                                    /* It might have been this window */
  1197.  
  1198.     thisWindow = GoodWNum(iNum);
  1199.     if(thisWindow)
  1200.         HideWindow(thisWindow->wWindow);
  1201.     }
  1202.  
  1203.     
  1204.  
  1205. void GetWindowRect(short n,Rect *r)
  1206. /*
  1207.   * return the window's current rectangle
  1208.   * in global coˆrdinate space.
  1209.   */
  1210.     {
  1211.     tEasyWindow *thisWindow;
  1212.     WindowPtr g;
  1213.  
  1214.     if(!(thisWindow = GoodWNum(n)))
  1215.         return;
  1216.  
  1217.     if(thisWindow->wUsed)
  1218.         {
  1219.         g = thisWindow->wWindow;
  1220.         SetPort(g);
  1221.         *r = g->portRect;
  1222.         LocalToGlobal((Point *)r);
  1223.         LocalToGlobal((Point *)( (char*)r + 4));
  1224.         }
  1225.     }
  1226.         
  1227. WindowPtr GetWindowPtr(short n)
  1228. /*
  1229.   * return the windowptr for
  1230.   * the specified window number
  1231.   */
  1232.     {
  1233.     tEasyWindow *thisWindow;
  1234.     WindowPtr g;
  1235.  
  1236.     if(!(thisWindow = GoodWNum(n)))
  1237.         g = 0;
  1238.     else
  1239.         g = thisWindow->wWindow;
  1240.  
  1241.     return g;
  1242.     }
  1243.  
  1244. boolean GetWindowVisible(short n)
  1245. /*
  1246.   * return true if the window exists,
  1247.   * and is visible, or false if its invisible
  1248.   * or doesn't exist.
  1249.   */
  1250.     {
  1251.     register WindowPtr g;
  1252.  
  1253.     g = GetWindowPtr(n);
  1254.     if(g)
  1255.         return ((WindowPeek)g)->visible;
  1256.     else
  1257.         return false;
  1258.     }
  1259.  
  1260. void SaveWindowPosition(short n)
  1261. /*
  1262.   * Save the position of window number n,
  1263.   * or all windows if n = -1;
  1264.   */
  1265.     {
  1266.     Rect **rH;
  1267.     register Rect *r;
  1268.     register short i;
  1269.     register short n1,n2;
  1270.     tEasyWindow *thisWindow;
  1271.  
  1272.     rH = (Rect **)NewHandle(sizeof(Rect));
  1273.     FailNil((long)rH);
  1274.     HLock((Handle)rH);
  1275.     r = *rH;
  1276.  
  1277.     if(n < 0)
  1278.         {
  1279.         n1 = 0;
  1280.         n2 = gEasyWindowListSize-1;
  1281.         }
  1282.     else
  1283.         n1 = n2 = n;
  1284.  
  1285.     for(i = n1; i<=n2; i++)
  1286.         {
  1287.         thisWindow = GoodWNum(i);
  1288.         if(thisWindow && thisWindow->wUsed)
  1289.             {
  1290.             GetWindowRect(i,r);
  1291.             if( !((WindowPeek)(thisWindow->wWindow))->visible )
  1292.                 SwapShort(r->left,r->right);
  1293.             Replace1Resource((Handle)rH,kWinPosType,i);
  1294.             }
  1295.         }
  1296.  
  1297.     DisposHandle( (Handle)rH );
  1298.     }
  1299.  
  1300. void ForgetWindowPosition(short n)
  1301. /*
  1302.   * Forget the saved window position n,
  1303.   * or all windows if n<0.
  1304.   */
  1305.     {
  1306.     register short i;
  1307.     register short n1,n2;
  1308.     register tEasyWindow *thisWindow;
  1309.  
  1310.     if(n < 0)
  1311.         {
  1312.         n1 = 0;
  1313.         n2 = gEasyWindowListSize-1;
  1314.         }
  1315.     else
  1316.         n1 = n2 = n;
  1317.  
  1318.     for(i = n1; i<=n2; i++)
  1319.         {
  1320.         thisWindow = GoodWNum(i);
  1321.         if(thisWindow && thisWindow->wUsed)
  1322.             Replace1Resource(0,kWinPosType,i);
  1323.         }
  1324.     }
  1325.  
  1326.  
  1327. void Replace1Resource(Handle h,long type,short id)
  1328. /*
  1329.   * This is AddResource with a
  1330.   * RmveResource if necessary.
  1331.   * Pass h==nil to delete the resource.
  1332.   */
  1333.     {
  1334.     Handle old;
  1335.  
  1336.     /*
  1337.      * A lame hack to prevent writing resources
  1338.      * to a lightspeed project file.
  1339.      */
  1340.     if( *(StringPtr)(0x910 + (*(StringPtr)0x910)) == '[pi]')
  1341.         {
  1342.         /* do nothing */
  1343.         }
  1344.     else
  1345.         {
  1346.  
  1347.         old = Get1Resource(type,id);
  1348.         if(old)
  1349.             RmveResource(old);
  1350.         if(h)
  1351.             {
  1352.             AddResource(h,type,id,(StringPtr)"\p");
  1353.             WriteResource(h);
  1354.             DetachResource(h);
  1355.             }
  1356.  
  1357.         }
  1358.     }
  1359.  
  1360. void CheckMenubar(void)
  1361.     {
  1362.     if(gInvalidMenuBar)
  1363.         {
  1364.         DrawMenuBar();
  1365.         gInvalidMenuBar = false;
  1366.         }
  1367.     }
  1368.  
  1369. /************************************
  1370. * Event Routines
  1371. ************************************/
  1372.  
  1373.  
  1374. void EventLoop(void)
  1375.     {
  1376.     EventRecord er;
  1377.     short i;
  1378.     register short wNum;
  1379.     WindowPtr w;
  1380.     register tEasyWindow *thisEasyWindow;
  1381.     Boolean tookKey,tookEvent;
  1382.     Rect r;
  1383.  
  1384.     CheckMenubar();
  1385.  
  1386.     WaitNextEvent(0xffff,&er,gSleep,nil);
  1387.         {
  1388.         gLastModifiers = er.modifiers;
  1389.  
  1390.         if(er.what > 5 && er.what < 12)                    /* update event or higher: in message    */
  1391.             w = (WindowPtr)er.message;
  1392.         else
  1393.             w = FrontWindow();                            /* else, use FrontW                    */
  1394.  
  1395.         if(er.what > 1)
  1396.             {
  1397.             wNum = ScanWindowList(w);                    /* other than null or click, scan list        */
  1398.             thisEasyWindow = GoodWNum(wNum);            /* and get record                    */
  1399.             }
  1400.         else
  1401.             thisEasyWindow = 0;
  1402.  
  1403.         SetPort(w);
  1404.  
  1405.         if(thisEasyWindow && thisEasyWindow->wEventProc)
  1406.             (*thisEasyWindow->wEventProc)(wNum,&er,&tookEvent);
  1407.         else
  1408.             tookEvent = 0;
  1409.  
  1410.         if(!tookEvent)
  1411.             switch (er.what)
  1412.                 {
  1413.                 case 0:    /* null event */
  1414.                     break;
  1415.     
  1416.                 case mouseDown:
  1417.                     FrontDAEdits();
  1418.                     DoMouseClick(&er);
  1419.                     break;
  1420.     
  1421.                 case keyDown:
  1422.                 case autoKey:
  1423.                     FrontDAEdits();
  1424.     
  1425.                     tookKey = false;
  1426.                     if( (!gMenuNeedsCmdKey) || (er.modifiers & 256) )
  1427.                         tookKey = DoKeyPress(er.message);
  1428.     
  1429.                     if(!tookKey && ((!gMenuNeedsCmdKey) || (er.modifiers & 256)) )
  1430.                         tookKey = CoolBigEasyCmdKeys(er.message & 0xFF);
  1431.     
  1432.                     if(!tookKey)
  1433.                         if(thisEasyWindow)
  1434.                             {
  1435.                             beKeyProcPtr fp;
  1436.                             
  1437.                             fp = thisEasyWindow->wKeyProc;
  1438.                             if(fp)
  1439.                                 {
  1440.                                 SetPort(thisEasyWindow->wWindow);                /* Set port to window    */
  1441.                                 (*fp)(wNum,            /* Call key proc        */
  1442.                                         (short)(er.message&0xff),            /* with the key */
  1443.                                         (short)((er.message>>8)&0xff),        /* the key code */
  1444.                                         er.modifiers);                        /* and the modifiers */
  1445.                                 }
  1446.                             }
  1447.                     break;
  1448.     
  1449.                 case updateEvt:
  1450.                     if(thisEasyWindow)
  1451.                         {
  1452.                         Rect visBounds,dummyRect;
  1453.                         beUpdateProcPtr fp;
  1454.                         
  1455.                         BeginUpdate(w);
  1456.     
  1457.                         visBounds = (**w->visRgn).rgnBBox;
  1458.                         fp = thisEasyWindow->wUpdateProc;
  1459.                         if(fp)
  1460.                             {
  1461.                             SetPort(thisEasyWindow->wWindow);                    /* Set port to window    */
  1462.                             (*fp)(wNum);            /* Call drawing proc        */
  1463.                             }
  1464.     
  1465.                         SetOrigin(0,0);
  1466.     
  1467.                         if (thisEasyWindow->flags & wGrowable)            /* Draw growbox, if...    */
  1468.                             MyDrawGrowIcon(w);
  1469.     
  1470.                         ClipRect(&gBigRect);
  1471.     
  1472.                         EndUpdate((WindowPtr)er.message);
  1473.                         }
  1474.                     break;
  1475.     
  1476.                 case activateEvt:
  1477.                     FrontDAEdits();
  1478.                     if(thisEasyWindow)
  1479.                         {
  1480.                         EnDisEdits(-1,-1,-1,-1,-1);
  1481.     
  1482.                         if(er.modifiers & 1)
  1483.                             {
  1484.                         activateMe:
  1485.                             {
  1486.                             beActivateProcPtr fp;
  1487.                         
  1488.                             fp = thisEasyWindow->wActivateProc;
  1489.                             if(fp)
  1490.                                 (*fp)(wNum);
  1491.                             }
  1492.                             }
  1493.                         else
  1494.                             {
  1495.                         deactivateMe:
  1496.                             {
  1497.                             beDeactivateProcPtr fp;
  1498.                             
  1499.                             fp = thisEasyWindow->wDeactivateProc;
  1500.                             if(fp)
  1501.                                 (*fp)(wNum);
  1502.                             }
  1503.                             }
  1504.     
  1505.                         InitCursor();
  1506.                         if (thisEasyWindow->flags & wGrowable)            /* Draw growbox, if...    */
  1507.                             MyDrawGrowIcon(w);
  1508.                         }
  1509.                     break;
  1510.     
  1511.                 case kOSEvent:
  1512.                     switch ((unsigned long) er.message >> 24)    /*  high byte of message  */
  1513.                         {
  1514.                          case kSuspendResumeMessage:
  1515.                             if(thisEasyWindow)                    /* just like activate event... */
  1516.                                 {
  1517.                                 EnDisEdits(-1,-1,-1,-1,-1);
  1518.                                 if(er.message & kResumeMask)
  1519.                                     goto activateMe;
  1520.                                 else
  1521.                                     goto deactivateMe;
  1522.                                 }
  1523.                         break;
  1524.                         }
  1525.                     break;
  1526.     
  1527.                 case kHighLevelEvent:
  1528.                     AEProcessAppleEvent(&er);
  1529.                     break;
  1530.     
  1531.                 default:
  1532.                     /*Debugger();/**/
  1533.                     ;
  1534.                 }
  1535.         }
  1536.  
  1537.     /*
  1538.       * See if we're doing a fake cool drag-window
  1539.       */
  1540.     if(gCoolDragState)
  1541.         {
  1542.         Point p,q;
  1543.  
  1544.         SetPort(gCoolDragWindow);
  1545.         GetMouse(&p);
  1546.         LocalToGlobal(&p);
  1547.         if( (p.v!=gCoolDragPoint.v) || (p.h!=gCoolDragPoint.h) )
  1548.             {
  1549.             q.h = gCoolDragWindow->portRect.left;
  1550.             q.v = gCoolDragWindow->portRect.top;
  1551.             LocalToGlobal(&q);
  1552.             MoveWindow(gCoolDragWindow,
  1553.                     q.h+p.h-gCoolDragPoint.h,
  1554.                     q.v+p.v-gCoolDragPoint.v,0);
  1555.             gCoolDragPoint = p;
  1556.             }
  1557.         if(!Button())
  1558.             gCoolDragState = 0;
  1559.         }
  1560.  
  1561.     SystemTask();
  1562.     w = FrontWindow();
  1563.     if ( w == gLastFrontIdle)                    /* Minor optimization, wins if the same        */
  1564.         wNum = gLastFrontWindowNumber;        /* window is frontmost for a while.            */
  1565.     else
  1566.         {
  1567.         wNum = ScanWindowList(w);
  1568.         gLastFrontIdle = w;
  1569.         gLastFrontWindowNumber = wNum;
  1570.         }
  1571.  
  1572.     if(er.what != mouseDown && er.what != activateEvt)    /* anything but a mousedown or [de]activate */
  1573.         for(i = 1; i<gEasyWindowListSize; i++)
  1574.             {
  1575.             if(gEasyWindowList[i].wUsed && gEasyWindowList[i].wIdleProc)
  1576.                 {
  1577.                 SetPort(gEasyWindowList[i].wWindow);
  1578.                 (*gEasyWindowList[i].wIdleProc)((short)i,(boolean)(w == gEasyWindowList[i].wWindow));
  1579.                 }
  1580.             }
  1581.  
  1582.     if (gMasterIdleProc)
  1583.         (*gMasterIdleProc)();
  1584.     }
  1585.  
  1586.  
  1587. Boolean CoolBigEasyCmdKeys(short key)
  1588.     {
  1589.     WindowRecord *w;
  1590.  
  1591.     switch(key)
  1592.         {
  1593.         /*
  1594.          * Rotate active window
  1595.          */
  1596.         case 9:        /* <tab> */
  1597.             w = *(WindowRecord **)0x9D6;        /* windowlist */
  1598.             if(w)
  1599.                 {
  1600.                 while (w->nextWindow)
  1601.                     w = w->nextWindow;
  1602.                 SelectWindow((WindowPtr)w);
  1603.                 }
  1604.             break;
  1605.  
  1606.         default:
  1607.             return false;
  1608.         }
  1609.     return true;
  1610.     }
  1611.  
  1612.  
  1613. void IdleWindow(short n)
  1614. /*
  1615.  * Idle window number n, or
  1616.  * -1 to idle all windows.
  1617.  */    
  1618.     {
  1619.     register short i;
  1620.     short lo,hi;
  1621.     WindowPtr w;
  1622.     register tEasyWindow *ew;
  1623.  
  1624.     if(n<0)
  1625.         {
  1626.         lo = 1;
  1627.         hi = gEasyWindowListSize;
  1628.         }
  1629.     else
  1630.         {
  1631.         lo = n;
  1632.         hi = n + 1;
  1633.         }
  1634.  
  1635.     w = FrontWindow();
  1636.     ew = &gEasyWindowList[lo];
  1637.  
  1638.     for(i = lo; i < hi; i++)
  1639.         {
  1640.         if(ew->wUsed && ew->wIdleProc)
  1641.             (*ew->wIdleProc)((short)i,ew->wWindow == w);
  1642.         ew++;
  1643.         }
  1644.  
  1645.     SystemTask();
  1646.     }    
  1647.  
  1648. void MyDrawGrowIcon(WindowPtr w)
  1649.     {
  1650.     Rect r;
  1651.  
  1652.     SetPort(w);
  1653.     GetGrowRect(w,&r);
  1654.     ClipRect(&r);
  1655.     DrawGrowIcon(w);
  1656.     ClipRect(&gBigRect);
  1657.     }
  1658.  
  1659.  
  1660. void SetMasterOpenAppMessage(EventHandlerProcPtr openAppProc)
  1661.     {
  1662.     if(gHasAppleEvents)
  1663.         AEInstallEventHandler(kCoreEventClass, kAEOpenApplication,
  1664.                 openAppProc, 0, false);
  1665.     }
  1666.  
  1667. void SetMasterOpenDocMessage(EventHandlerProcPtr openDocProc)
  1668.     {
  1669.     if(gHasAppleEvents)
  1670.         AEInstallEventHandler(kCoreEventClass, kAEOpenDocuments,
  1671.                 openDocProc, 0, false);
  1672.     }
  1673.  
  1674. void InitBigEasy(void)
  1675.     {
  1676.     long result;
  1677.  
  1678.     InstallMyExitToShell();
  1679.     gMasterIdleProc = nil;
  1680.     gAboutProc = nil;
  1681.     gQuitApp = false;
  1682.     gMenuNeedsCmdKey = true;
  1683.     gStaggerWindows = true;
  1684.     gSleep = 0;
  1685.     gInvalidMenuBar = false;
  1686.  
  1687.     SetRect(&gBigRect,-16000,-16000,16000,16000);
  1688.  
  1689.     gEasyWindowListH = (tEasyWindow**)NewHandle(sizeof(tEasyWindow));
  1690.     HLock((Handle)gEasyWindowListH);
  1691.     gEasyWindowList = *gEasyWindowListH;
  1692.     gEasyWindowList[0].wUsed = 0;
  1693.     gEasyWindowListSize = 1;
  1694.  
  1695.     gLastFrontIdle = (WindowPtr) 0;
  1696.     gLastFrontWindowNumber = -1;
  1697.  
  1698.     gCoolDragState = 0;
  1699.  
  1700.  
  1701. /*
  1702.  * 7.0 Feature stuff
  1703.  */
  1704.     gHasAppleEvents = (Gestalt(gestaltAppleEventsAttr, &result) ? false : result != 0);
  1705.     }
  1706.  
  1707. void main(void)
  1708.     {
  1709. #if 0
  1710. #ifdef THINK_C_PROFILE
  1711.     freopen("profile output","w+",stdout);
  1712.  
  1713.     InitProfile(1000,50);
  1714. #endif THINK_C_PROFILE    
  1715. #endif
  1716.  
  1717.     MaxApplZone();
  1718.     MoreMasters();
  1719.     MoreMasters();
  1720.  
  1721.     InitToolbox();
  1722.     StartMenus();
  1723.  
  1724.     InitBigEasy();
  1725.     Bootstrap();
  1726.     
  1727.     #if THINK_C >= 5
  1728.         #if defined(STACK_KILLER) || defined(TIMING_PROFILE)
  1729.             prepStackKiller();        /** slime from HELL **/
  1730.             #ifdef TIMING_PROFILE
  1731.                 InitTimingProfile(150);    /* call depth */
  1732.             #endif TIMING_PROFILE
  1733.         #endif
  1734.     #endif
  1735.  
  1736.     while (!gQuitApp)
  1737.         EventLoop();
  1738.  
  1739.     FlushEvents(0xffff,0);
  1740.  
  1741.     #ifdef TIMING_PROFILE
  1742.         DumpProfile(0, 0, "\ptiming stats");
  1743.     #endif
  1744.  
  1745.     ExitToShell();
  1746.     }
  1747.